package fr.emse.tatiana.corpus;

import java.io.File;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import fr.emse.tatiana.display.PropertyFile;
import fr.emse.tatiana.filter.CatWriter;

/**
 * A trace file in a corpus, complete with information about synchronisation and replay
 * 
 * @author dyke
 *
 */
public class CorpusFile {
	
	private String path;
	private int type;
	private String replayer;
	private long firsttime;
	private long lasttime;
	private long delta;
	private Corpus corpus;
	private IFile file;
	private PropertyFile pf;
	
	
		
	/**
	 * @param path absolute system path to the file
	 * @param type one of UNKNOWN, VIDEO, XML, TEXT, FORESTXML, CSV 
	 * @param replayer name of replayer "none" if no replayer
	 * @param firsttime replayer's understanding of the first time (video = 0, trace = utc time)
	 * @param lasttime replayer's understanding of the last time
	 * @param delta 
	 * @param corpus
	 */
	public CorpusFile(String path, int type, String replayer, long firsttime, long lasttime, long delta) {
		this.path = path;
		this.type = type;
		this.replayer = replayer;
		this.firsttime = firsttime;
		this.lasttime = lasttime;
		this.delta = delta;
	}

	public CorpusFile (IFile file) {
		this(file.getLocation().toString(), UNKNOWN, "none", 0, 0, 0);
		setFile(file);
		try {
			this.type = Integer.parseInt(pf.getProperty(typeqn));
			this.replayer = pf.getProperty(replayerqn);
			this.delta = Long.parseLong(pf.getProperty(deltaqn));
			this.firsttime = Long.parseLong(pf.getProperty(firstqn));
			this.lasttime = Long.parseLong(pf.getProperty(lastqn));	
		} catch (NumberFormatException e) {
			// is what happens when corpusfile has never been imported
			// TODO soon add import wizard
		}
	}
	
	public String getReplayer() {
		return replayer;
	}
	
	public long getDelta() {
		return delta;
	}

	public void setLastTime(long lasttime) {
		this.lasttime = lasttime;
	}

	public void setDelta(long delta) {
		this.delta = delta;
	}

	public void setFirstTime(long firsttime) {
		this.firsttime = firsttime;
	}

	public void setReplayer(String replayer) {
		this.replayer = replayer;
	}

	public void setType(int type) {
		this.type = type;
	}

	public long getFirstTime() {
		return firsttime;
	}
	public long getLastTime() {
		return lasttime;
	}
	public String getName() {
		return new File(path).getName();
	}
	public String getPath() {
		return path;
	}
	public int getType() {
		return type;
	}
	
	@Override
	public String toString() {
		return getName();
	}
	
	
	/**
	 * Used to treat files which are not yet in the workspace
	 * 
	 * @return
	 */
	public String getXmlFileURI() {
		try {
			String value = new File(this.getXmlFilePath()).toURI().getPath();
			return value;
		} catch (NullPointerException e) {
			return null;
		}
	}
	

	public String getXmlFileWorkspacePath() {
		if (this.file == null) {
			return null;
		}
		if (type==FORESTXML || type== CSV || type == SEG || type == AUDIOSEG) {
			getXmlFilePath();
			try {
				file.getParent().refreshLocal(IResource.DEPTH_ONE, null);
			} catch (CoreException e) {
				// doesn't matter
			}
			return file.getParent().findMember("." + file.getName() + ".xml").getFullPath().makeRelative().toString();
		} else {
			return file.getFullPath().makeRelative().toString();
		}
	}
	

	private String getXmlFilePath() {
		switch (type) {
		case XML:
			return path;
		case FORESTXML:
			try { //TODO z later add caching
				File file = new File(path);
				String xmlname = file.getParent() + File.separator + "." + file.getName() + ".xml";
				CatWriter w = new CatWriter(xmlname);
				w.write("<trace>\n");
				w.add(path);
				w.write("</trace>");
				w.flush();
				w.close();
				return xmlname;
			}catch (Exception e) {
				return null;
			}
		case CSV:
			try { //TODO z later add caching
				File file = new File(path);
				String xmlname = file.getParent() + File.separator + "." + file.getName() + ".xml";
				CSVWriter w = new CSVWriter(xmlname);
				w.convert(path,file.getName());
				return xmlname;
			}catch (Exception e) {
				return null;
			}
		case SEG:
			try { //TODO z later add caching
				File file = new File(path);
				String xmlname = file.getParent() + File.separator + "." + file.getName() + ".xml";
				SEGWriter w = new SEGWriter(xmlname);
				w.convert(path,file.getName());
				return xmlname;
			}catch (Exception e) {
				return null;
			}
		case AUDIOSEG:
			try { //TODO z later add caching
				File file = new File(path);
				String xmlname = file.getParent() + File.separator + "." + file.getName() + ".xml";
				AudioSegWriter w = new AudioSegWriter(xmlname);
				w.convert(path,file.getName());
				return xmlname;
			}catch (Exception e) {
				return null;
			}
		default:	
			return null;
		}
	}

	public final static int UNKNOWN = 0;
	public final static int XML = 1;
	public final static int VIDEO = 2;
	public final static int TEXT = 3;
	public final static int FORESTXML = 4;
	public final static int CSV = 5;
	public final static int SEG = 6;
	public final static int AUDIOSEG = 7;
	
	public void setFile(IFile file) {
		this.file = file;
		this.pf = new PropertyFile(file.getParent().getFile(new Path("."+file.getName()+".metadata")));
	}
	
	public void save() {
		if (file==null) return;
		pf.setProperty(typeqn, ""+type);
		pf.setProperty(replayerqn, ""+replayer);
		pf.setProperty(deltaqn, ""+delta);
		pf.setProperty(firstqn, ""+firsttime);
		pf.setProperty(lastqn, ""+lasttime);
		pf.save();
	}
	
	public static String XMLfileURIToName(String value) {
		String name = new File(value).getName();
		if (name.startsWith(".")) {
			return name.substring(1, name.length()-4);
		}
		return name;
	}
	
	public static final String typeqn = "fr.emse.tatiana.type";
	public static final String replayerqn = "fr.emse.tatiana.replayer";
	public static final String firstqn = "fr.emse.tatiana.first";
	public static final String lastqn = "fr.emse.tatiana.last";
	public static final String deltaqn = "fr.emse.tatiana.delta";
	
	@SuppressWarnings("serial")
	private static class CFException extends Exception {
		public CFException(String s) {
			super(s);
		}
	}
}

